package com.fin.zw.aiqas.service;

import com.fin.zw.aiqas.entity.LogInfo;
import com.fin.zw.aiqas.entity.QLogInfo;
import com.fin.zw.aiqas.model.request.LogRequest;
import com.fin.zw.aiqas.model.session.SessionModel;
import com.fin.zw.aiqas.repository.LogInfoRepository;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;

@Service("logInfoService")
public class LogInfoService {

    private static final Logger log = LoggerFactory.getLogger(LogInfoService.class);

    @Autowired
    private LogInfoRepository logInfoRepository;

    @Autowired
    private RedisTemplate<String, SessionModel> redisTemplate;

    /**
     * 日志的添加
     *
     * @param joinPoint
     */
    public void addLog(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String accessToken = request.getHeader("authorization");
        SessionModel sessionModel = new SessionModel();
        if (StringUtils.isNotEmpty(accessToken)) {
            log.info("身份校验：" + accessToken);
            sessionModel = redisTemplate.opsForValue().get("operator:token:" + accessToken.split(" ")[1]);
        }
        // 记录下请求内容
        log.info("URL : " + request.getRequestURL().toString());
        Signature signature = joinPoint.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
        String param = Arrays.toString(joinPoint.getArgs());
        try {
            if (!request.getMethod().equals("GET")) {
                LogInfo logInfo = new LogInfo();
                if (Objects.nonNull(sessionModel)) {
                    logInfo.setUserName(sessionModel.getUserName());
                }
                String describe = getOperationShortLog(joinPoint);
                logInfo.setClassName(className);
                logInfo.setMethodName(methodName);
                logInfo.setMethodType(request.getMethod());
                logInfo.setRecordTime(new Date());
                logInfo.setVisitIp(request.getRemoteAddr());
                logInfo.setRemark(describe);
                logInfo.setParam(param);
                logInfoRepository.save(logInfo);
            }
        } catch (Exception e) {
            log.error("保存日志出错：" + e.getMessage());
        }
    }

    /**
     * 获取控制器中的注释
     *
     * @param joinPoint
     * @return
     */
    private String getOperationShortLog(JoinPoint joinPoint) {
        String text = "";
        Class targetClass = joinPoint.getSignature().getDeclaringType();
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
            if (StringUtils.equals(method.getName(), joinPoint.getSignature().getName())) {
                ApiOperation annotation = method.getAnnotation(ApiOperation.class);
                if (annotation != null) {
                    text = annotation.value();
                }
            }
        }
        return text;
    }

    /**
     * 分页查询操作日志
     *
     * @param pageable
     * @param request
     * @return
     */
    public Page<LogInfo> queryLogInfo(Pageable pageable, LogRequest request) {
        BooleanBuilder builder = new BooleanBuilder();
        QLogInfo qLogInfo = QLogInfo.logInfo;
        if (StringUtils.isNotEmpty(request.getUserName())) {
            builder.and(qLogInfo.userName.eq(request.getUserName()));
        }
        if (StringUtils.isNotEmpty(request.getVisitIp())) {
            builder.and(qLogInfo.visitIp.eq(request.getVisitIp()));
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            builder.and(qLogInfo.recordTime.between(request.getStartTime(), request.getEndTime()));
        }
        Page<LogInfo> page = logInfoRepository.findAll(builder, pageable);
        return page;
    }
}
